package com.baitiaojun.common.utils.thread;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

@Slf4j
public class ThreadsUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadsUtils.class);

    /**
     * 休眠线程, 指定毫秒数
     * @param milliseconds
     */
    public static void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 关闭线程池
     * @param executorService
     */
    public static void shutdown(ExecutorService executorService) {
        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown(); //关闭线程池, 等待当前线程任务执行完毕, 清空队列和挂起线程
            try {
                if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                    executorService.shutdownNow(); //超时则立刻关闭线程池
                }
            } catch (InterruptedException e) {
                executorService.shutdownNow(); //立刻关闭线程池
                Thread.currentThread().interrupt(); //如果是当前线程, 就直接中断
            }
        }
    }

    /**
     * 获取runnable任务的返回结果, 失败则中断当前线程并打印日志, 且不阻断主线程
     * @param r
     * @return
     */
    public static Object getResult(Runnable r) {
        FutureTask<?> futureTask = new FutureTask<>(Executors.callable(r));
        try {
            if (futureTask.isDone()) {
                return futureTask.get();
            }
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.warn(e.getMessage());
            Thread.currentThread().interrupt();
        }
        return null;
    }

    /**
     * 打印线程异常信息
     */
    public static void printException(Runnable r, Throwable throwable) {
        try {
            FutureTask<?> future = new FutureTask<>(Executors.callable(r));
            if (future.isDone()) {
                future.get();
            }
        } catch (CancellationException e) {
            throwable = e;
        } catch (ExecutionException e) {
            throwable = e.getCause();
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
        if (throwable != null) {
            log.error(throwable.getMessage(), throwable);
        }
    }

}
